package com.sccba.uop.demo.util;

import com.sccba.uop.demo.common.constant.RequestHeaderField;
import com.sccba.uop.demo.common.constant.ResponseHeaderField;
import com.sccba.uop.demo.util.algorithm.Base64Utils;
import com.sccba.uop.demo.util.algorithm.SHA256Utils;
import com.sccba.uop.demo.util.algorithm.SM3Utils;
import okhttp3.Headers;

import java.nio.charset.StandardCharsets;
import java.util.*;

public class SignatureUtils {

    public static String buildReqSignContentWithSHA256(Headers.Builder requestHeader, String jsonBody) {
        String base64Body = Base64Utils.encodeToString(SHA256Utils.hash(jsonBody.getBytes(StandardCharsets.UTF_8)));
        Map<String, String> params = new HashMap<>();
        params.put("Body", base64Body);
        params.put(RequestHeaderField.X_UOP_API_CODE.getName(), requestHeader.get(RequestHeaderField.X_UOP_API_CODE.getName()));
        params.put(RequestHeaderField.X_UOP_APP_ID.getName(), requestHeader.get(RequestHeaderField.X_UOP_APP_ID.getName()));
        params.put(RequestHeaderField.X_UOP_TIMESTAMP.getName(), requestHeader.get(RequestHeaderField.X_UOP_TIMESTAMP.getName()));
        params.put(RequestHeaderField.X_UOP_UNIQUE_NO.getName(), requestHeader.get(RequestHeaderField.X_UOP_UNIQUE_NO.getName()));
        params.put(RequestHeaderField.X_UOP_AUTH_TOKEN.getName(), requestHeader.get(RequestHeaderField.X_UOP_AUTH_TOKEN.getName()));
        return sort(params);
    }

    public static String buildRespSignContentWithSHA256(Headers responseHeader, byte[] plainRespMsg) {
        String base64Body = Base64Utils.encodeToString(SHA256Utils.hash(plainRespMsg));
        Map<String, String> params = new HashMap<>();
        params.put("Body", base64Body);
        params.put(ResponseHeaderField.X_UOP_UNIQUE_NO.getName(), responseHeader.get(ResponseHeaderField.X_UOP_UNIQUE_NO.getName()));
        return sort(params);
    }

    public static String buildReqSignContentWithSM3(Headers.Builder requestHeader, String jsonBody) {
        String base64Body = Base64Utils.encodeToString(SM3Utils.hash(jsonBody.getBytes(StandardCharsets.UTF_8)));
        Map<String, String> params = new HashMap<>();
        params.put("Body", base64Body);
        params.put(RequestHeaderField.X_UOP_API_CODE.getName(), requestHeader.get(RequestHeaderField.X_UOP_API_CODE.getName()));
        params.put(RequestHeaderField.X_UOP_APP_ID.getName(), requestHeader.get(RequestHeaderField.X_UOP_APP_ID.getName()));
        params.put(RequestHeaderField.X_UOP_TIMESTAMP.getName(), requestHeader.get(RequestHeaderField.X_UOP_TIMESTAMP.getName()));
        params.put(RequestHeaderField.X_UOP_UNIQUE_NO.getName(), requestHeader.get(RequestHeaderField.X_UOP_UNIQUE_NO.getName()));
        params.put(RequestHeaderField.X_UOP_AUTH_TOKEN.getName(), requestHeader.get(RequestHeaderField.X_UOP_AUTH_TOKEN.getName()));
        return sort(params);
    }

    public static String buildRespSignContentWithSM3(Headers responseHeader, byte[] plainRespMsg) {
        String base64Body = Base64Utils.encodeToString(SM3Utils.hash(plainRespMsg));
        Map<String, String> params = new HashMap<>();
        params.put("Body", base64Body);
        params.put(ResponseHeaderField.X_UOP_UNIQUE_NO.getName(), responseHeader.get(ResponseHeaderField.X_UOP_UNIQUE_NO.getName()));
        return sort(params);
    }

    private static String sort(Map<String, String> params) {
        StringBuilder content = new StringBuilder();
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);
        boolean first = true;
        for (String key : keys) {
            String value = params.get(key);
            if (key != null && !"".equals(key)
                    && value != null && !"".equals(value)) {
                content.append(first ? "" : "&");
                content.append(String.format("%s=%s", key, value));
                first = false;
            }
        }
        return content.toString();
    }

}
